﻿#region Using Directives

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;

    using Csla;

    using MarketPulse.BusinessLogic.Core;


#endregion

namespace MarketPulse.BusinessLogic.Common
{    
    /// <summary>
    /// A class representing an Enquiry 
    /// </summary>
    [Serializable]
    [Csla.Server.ObjectFactory("MarketPulse.DataAccess.Factory.EnquiryFactory, MarketPulse.DataAccess.Factory")]
    public class Enquiry : MarketPulseBase<Enquiry>
    {
        #region Constructors

            /// <summary>
            /// Default constructor for this class, marked as private in order to (try to) enforce construction
            /// only via the static factory methods provided.
            /// </summary>
            private Enquiry()
            {

            }

        #endregion

        #region Methods

            #region Factory Methods

                /// <summary>
                /// Method used to create (instantiate) a new Enquiry via the DataPortal client proxy
                /// </summary>
                /// <returns>A valid (newly created) Enquiry BusinessObject</returns>
                public static Enquiry New()
                {
                    return DataPortal.Create<Enquiry>();
                }                

                /// <summary>
                /// Method used to retrieve a specific Enquiry based on it's associated Guid (via the DataPortal client proxy)
                /// </summary>
                /// <param name="guid">The GUID of the program to retrieve</param>
                /// <returns>A valid (populated) Program BusinessObject</returns>
                public static Enquiry Get(Guid guid)
                {
                    return DataPortal.Fetch<Enquiry>(new Csla.SingleCriteria<Guid>(guid));
                }

            #endregion       

            #region Business Process Methods

                /// <summary>
                /// Performs an action on this enquiry.
                /// </summary>
                /// <param name="actionGuid">The GUID of the action</param>
                /// <param name="comment">A comment</param>
                public void PerformAction(Guid actionGuid, string comment)
                {
                    // The XML has to be pulled out of the property to be able to update properly.
                    var enquiryXml = this.EnquiryXML;
                    var actionNode = new XElement("action", new XCData(comment));
                    actionNode.SetAttributeValue("actionguid", actionGuid);
                    actionNode.SetAttributeValue("userguid", this.ActionUserGUID.Value);
                    actionNode.SetAttributeValue("datetime", DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK"));
                    enquiryXml.Add(actionNode);
                    LoadProperty<string>(EnquiryXMLProperty, enquiryXml.ToString());
                }

            #endregion

        #endregion

        #region Properties

            #region Association GUID Properties (Foreign Keys)

                /// <summary>
                /// The GUID of the user (BusinessObject) that this Enquiry belongs to 
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> UserGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.UserGUID);
                /// <summary>
                /// The GUID of the user (BusinessObject) that this Enquiry belongs to 
                /// </summary>
                public Nullable<Guid> UserGUID
                {
                    get { return GetProperty(UserGUIDProperty); }
                    set { SetProperty(UserGUIDProperty, value); }
                }

                /// <summary>
                /// The GUID of the visit (BusinessObject) that this Enquiry belongs to 
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> VisitGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.VisitGUID);
                /// <summary>
                /// The GUID of the visit (BusinessObject) that this Enquiry belongs to 
                /// </summary>
                public Nullable<Guid> VisitGUID
                {
                    get { return GetProperty(VisitGUIDProperty); }
                    set { SetProperty(VisitGUIDProperty, value); }
                }

                /// <summary>
                /// The GUID of the EnquiryType
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> EnquiryTypeGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.EnquiryTypeGUID);
                /// <summary>
                /// The GUID of the EnquiryType
                /// </summary>
                public Nullable<Guid> EnquiryTypeGUID
                {
                    get { return GetProperty(EnquiryTypeGUIDProperty); }
                    set { SetProperty(EnquiryTypeGUIDProperty, value); }
                }

                /// <summary>
                /// The GUID of the EnquiryReason
                /// </summary>
                public static PropertyInfo<Nullable<Guid>> EnquiryReasonGUIDProperty = RegisterProperty<Nullable<Guid>>(p => p.EnquiryReasonGUID);
                /// <summary>
                /// The GUID of the EnquiryReason
                /// </summary>
                public Nullable<Guid> EnquiryReasonGUID
                {
                    get { return GetProperty(EnquiryReasonGUIDProperty); }
                    set { SetProperty(EnquiryReasonGUIDProperty, value); }
                }

            #endregion

            #region Association Objects
                
                /// <summary>
                /// The UserInfo object associated with the InsertUserGUID property against this Enquiry.
                /// </summary>
                public static PropertyInfo<UserInfo> LoggedByUserInfoProperty = RegisterProperty<UserInfo>(p => p.LoggedByUserInfo);
                /// <summary>
                /// The UserInfo object associated with the InsertUserGUID property against this Enquiry.
                /// </summary>
                public UserInfo LoggedByUserInfo
                {
                    get
                    {
                        if (!FieldManager.FieldExists(LoggedByUserInfoProperty))
                        {
                            LoadProperty(LoggedByUserInfoProperty, UserInfo.Get(this.InsertUserGUID));
                            OnPropertyChanged(LoggedByUserInfoProperty);
                        }
                        return ReadProperty(LoggedByUserInfoProperty);
                    }
                }

                /// <summary>
                /// The BranchInfo object associated with the VisitGUID property against this Enquiry.
                /// </summary>
                public static PropertyInfo<BranchInfo> BranchInfoProperty = RegisterProperty<BranchInfo>(p => p.BranchInfo);
                /// <summary>
                /// The BranchInfo object associated with the VisitGUID property against this Enquiry.
                /// </summary>
                public BranchInfo BranchInfo
                {
                    get
                    {
                        if (!FieldManager.FieldExists(BranchInfoProperty))
                        {
                            LoadProperty(BranchInfoProperty, BranchInfo.GetByVisitGUID(this.VisitGUID.Value));
                            OnPropertyChanged(BranchInfoProperty);
                        }
                        return ReadProperty(BranchInfoProperty);
                    }
                }

                ///// <summary>
                ///// The VisitInfo object associated with the VisitGUID property against this Enquiry.
                ///// </summary>
                //public static PropertyInfo<VisitInfo> VisitInfoProperty = RegisterProperty<VisitInfo>(p => p.VisitInfo);
                ///// <summary>
                ///// The VisitInfo object associated with the VisitGUID property against this Enquiry.
                ///// </summary>
                //public VisitInfo VisitInfo
                //{
                //    get
                //    {
                //        if (!FieldManager.FieldExists(VisitInfoProperty))
                //        {
                //            LoadProperty(VisitInfoProperty, VisitInfo.GetByGuid(this.VisitGUID.Value));
                //            OnPropertyChanged(VisitInfoProperty);
                //        }
                //        return ReadProperty(VisitInfoProperty);
                //    }
                //}

                /// <summary>
                /// The VisitInfo object associated with the VisitGUID property against this Enquiry.
                /// </summary>
                public static PropertyInfo<VisitInfo> VisitInfoProperty = RegisterProperty<VisitInfo>(p => p.VisitInfo);
                /// <summary>
                /// The VisitInfo object associated with the VisitGUID property against this Enquiry.
                /// </summary>
                public VisitInfo VisitInfo
                {
                    get
                    {
                        if (!FieldManager.FieldExists(VisitInfoProperty))
                        {
                            LoadProperty(VisitInfoProperty, VisitInfo.GetByGuid(this.VisitGUID.Value));
                            OnPropertyChanged(VisitInfoProperty);
                        }
                        return ReadProperty(VisitInfoProperty);
                    }
                }

                /// <summary>
                /// The EnquiryTypeInfo object associated with the EnquiryTypeGUID property against this Enquiry.
                /// </summary>
                public static PropertyInfo<EnquiryTypeInfo> EnquiryTypeInfoProperty = RegisterProperty<EnquiryTypeInfo>(p => p.EnquiryTypeInfo);
                /// <summary>
                /// The EnquiryTypeInfo object associated with the EnquiryTypeGUID property against this Enquiry.
                /// </summary>
                public EnquiryTypeInfo EnquiryTypeInfo
                {
                    get
                    {
                        if (!FieldManager.FieldExists(EnquiryTypeInfoProperty))
                        {
                            LoadProperty(EnquiryTypeInfoProperty, EnquiryTypeInfo.GetByGuid(this.EnquiryTypeGUID.Value));
                            OnPropertyChanged(EnquiryTypeInfoProperty);
                        }
                        return ReadProperty(EnquiryTypeInfoProperty);
                    }
                }

                /// <summary>
                /// The EnquiryReasonInfo object associated with the EnquiryReasonGUID property against this Enquiry.
                /// </summary>
                public static PropertyInfo<EnquiryReasonInfo> EnquiryReasonInfoProperty = RegisterProperty<EnquiryReasonInfo>(p => p.EnquiryReasonInfo);
                /// <summary>
                /// The EnquiryReasonInfo object associated with the EnquiryReasonGUID property against this Enquiry.
                /// </summary>
                public EnquiryReasonInfo EnquiryReasonInfo
                {
                    get
                    {
                        if (!FieldManager.FieldExists(EnquiryReasonInfoProperty))
                        {
                            LoadProperty(EnquiryReasonInfoProperty, EnquiryReasonInfo.GetByGuid(this.EnquiryReasonGUID.Value));
                            OnPropertyChanged(EnquiryReasonInfoProperty);
                        }
                        return ReadProperty(EnquiryReasonInfoProperty);
                    }
                }

                ///// <summary>
                ///// Not sure why this is here
                ///// </summary>
                //public static PropertyInfo<EnquiryActionTypeInfoList> ActionUserActionTypeInfoListProperty = RegisterProperty<EnquiryActionTypeInfoList>(p => p.ActionUserActionTypeInfoList);
                ///// <summary>
                ///// Not sure why this is here
                ///// </summary>
                //public EnquiryActionTypeInfoList ActionUserActionTypeInfoList
                //{
                //    get
                //    {
                //        if (!FieldManager.FieldExists(ActionUserActionTypeInfoListProperty))
                //        {

                //            LoadProperty(ActionUserActionTypeInfoListProperty, EnquiryActionTypeInfoList.GetByProfileGUID(this.ActionUserGUID.Value));
                //            OnPropertyChanged(ActionUserActionTypeInfoListProperty);
                //        }
                //        return ReadProperty(ActionUserActionTypeInfoListProperty);
                //    }
                //}

                ///// <summary>
                ///// Not sure why this is here...
                ///// </summary>
                //public static PropertyInfo<EnquiryActionTypeInfoList> ActionTypeInfoListProperty = RegisterProperty<EnquiryActionTypeInfoList>(p => p.ActionTypeInfoList);
                ///// <summary>
                ///// Not sure why this is here...
                ///// </summary>
                //public EnquiryActionTypeInfoList ActionTypeInfoList
                //{
                //    get
                //    {
                //        if (!FieldManager.FieldExists(ActionTypeInfoListProperty))
                //        {

                //            LoadProperty(ActionTypeInfoListProperty, EnquiryActionTypeInfoList.Get());
                //            OnPropertyChanged(ActionTypeInfoListProperty);
                //        }
                //        return ReadProperty(ActionTypeInfoListProperty);
                //    }
                //}

            #endregion

                /// <summary>
                /// The XML document that describes the enquiry.  
                /// Sadly, the property type is required to be a string because XElement is not marked
                /// [Serializable] and therefore cannot be used with the Csla framework.
                /// </summary>
                public static PropertyInfo<string> EnquiryXMLProperty = RegisterProperty<string>(p => p.EnquiryXML);
                /// <summary>
                /// The XML document that describes the enquiry.  
                /// Sadly, the property type is required to be a string because XElement is not marked
                /// [Serializable] and therefore cannot be used with the Csla framework.
                /// </summary>
                public System.Xml.Linq.XElement EnquiryXML
                {
                    get { return System.Xml.Linq.XElement.Parse(GetProperty(EnquiryXMLProperty)); }
                    set
                    {
                        mIsXmlDirty = true;
                        SetProperty(EnquiryXMLProperty, value.ToString(SaveOptions.DisableFormatting));
                    }
                }
                
                /// <summary>
                /// The comment to append to the Enquiry when performing a Save() on the object. This field is not required.
                /// </summary>
                public static PropertyInfo<string> CommentProperty = RegisterProperty<string>(p => p.Comment);
                /// <summary>
                /// The comment to append to the Enquiry when performing a Save() on the object. This field is not required.
                /// </summary>
                public string Comment
                {
                    get { return GetProperty(CommentProperty); }
                    set { SetProperty(CommentProperty, value); }
                }

                private bool mIsXmlDirty = false;
                /// <summary>
                /// Flag to indicate whether the Xml document property has been modified since this
                /// object was persisted.
                /// </summary>
                public bool IsXmlDirty
                {
                    get { return mIsXmlDirty; }
                }

        #endregion
    }
}
